#include "ql_oe.h"
#include "ql_sim.h"
#include "ql_nw.h"
#include "ql_wwan.h"
#include "ql_wwan_v2.h"
#include "../include/dial.hpp"
#include "../include/sys_var.hpp"
#include "../include/dtu.hpp"

#include <fstream>
#include <atomic>
#include <thread>
#include <string>
#include <atomic>

std::atomic<bool> finish(false);

void on_dail_result( ql_data_call_state_s *state )
{
	if( state == nullptr ) return;

	if( state->state  == QL_DATA_CALL_CONNECTED ){
		std::cout << " network connected." << std::endl;
	}else{
		std::cerr << " Can not network." << std::endl;
	}

	finish = true;
}

ec20dial :: ec20dial()
{
	try{
		check_sim();                  // 检查SIM卡是否就绪
		check_vendor();               // 检查SIM运营商
	}catch( err_code e ){
		std::cerr << "check sim and net work fail." << std::endl;
        StartRebootTimer();
	}
	// 初始化回调函数
	ql_data_call_init( on_dail_result );

	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ){
		ptvar->GetValue( "/net/vpn_sw" , is_apn );
		ptvar->GetValue( "/net/auto_2g" , auto_2g );

		if( is_apn ){
			ptvar->GetValue("/net/vpn/user" , user );
			ptvar->GetValue("/net/vpn/paswd" , paswd );
		}
		set_apn();
	}
}

ec20dial :: ~ec20dial()
{

}

void
ec20dial :: check_sim()
{
	// 检查SIM卡是否插入
	E_QL_SIM_STATES_T  state = QL_SIM_GetState( E_QL_SIM_EXTERNAL_SLOT_1 );
	switch( state ){
	case E_QL_SIM_STAT_NOT_INSERTED:
		std::cerr << "SIM card not inserted" << std::endl;
        StartRebootTimer();
        //reboot(RB_AUTOBOOT);
		break;
	case E_QL_SIM_STAT_READY:
		break;
	default:
        std::cerr << "Unknown   SIM card error" << std::endl;
        StartRebootTimer();
        // reboot( RB_AUTOBOOT );
		break;
	}

	return ;
}

ec20dial :: sim_vendor
ec20dial :: check_vendor()
{
	char imsi[ 25 ];
	memset( imsi , 0 , 25 );
	int e = QL_SIM_GetIMSI( E_QL_SIM_EXTERNAL_SLOT_1 , imsi , 25 );
	if( e ){  // 发生错误
		return VENDOR_UNKNOW;
	}else{// 操作正确
		std::string str( imsi );
		str = str.substr( 0 , 6 );
		if( str == "46000" ){// 中国移动
			vendor = CMCC;
		}else if( str == "46001" ){// 中国联通
			vendor = CUCC;
		}else if( str == "46003" ){// 中国电信
			vendor = CTCC;
		}else{
			vendor = VENDOR_UNKNOW;
		}
	}

	return vendor;
}

ec20dial :: sim_type
ec20dial :: check_radio()
{
	int                         e = 0, rssi , ber;
	sim_type                    ret;
	E_QL_NW_RADIO_ACCESS_TYPE_T radio;
	E_QL_WWAN_NET_REG_STATE_T   state;

	e = QL_NW_GetRegState( &radio , &state , &rssi , &ber );
        if( e ){
	    std::cerr << "read network registration fail." << std::endl;
	    return __NW_UNKNOWN;
	}
	switch( state ){
	case E_QL_WWAN_REG_NOT_REGISTERED:
	case E_QL_WWAN_REG_NOT_REGISTERED_SEARCHING_NOW:
		StartRebootTimer();
		break;
	case E_QL_WWAN_REG_REGISTERED_HOME_NETWORK:
	case E_QL_WWAN_REG_ROAMING:
		switch( radio ){
		case E_QL_NW_RAT_GSM:                          // 2G
			ret = _2G;
			break;
		case E_QL_NW_RAT_UTRAN:                        // 3G
			ret = _3G;
			break;
		case E_QL_NW_RAT_GSMW_EGPRS:                   // 2.5g
		      ret = _2G;
			break;
		case E_QL_NW_RAT_UTRANW_HSDPA:                 // 3.5g
			ret = _3G;
			break;
		case E_QL_NW_RAT_UTRANW_HSDPA_AND_HSUPA:       // 3.5
		      ret = _3G;
			break;
		case E_QL_NW_RAT_E_UTRAN:                      // 4G
		case E_QL_NW_RAT_UTRANW_HSUPA:
			ret = _4G;
			break;
		}
		break;
	case E_QL_WWAN_REG_DENIED:
		StartRebootTimer();
		break;
	case E_QL_WWAN_REG_UNKNOWN:
	default:
        StartRebootTimer();
		break;
	}

	return ret;
}

int ec20dial :: run()
{
	int ret = 0;

	if( check_csq() ){
		try{
			check_radio();

			ql_data_call_s    call_struct;

			call_struct.profile_idx = 0;
			call_struct.reconnect = true;
			call_struct.ip_family = QL_DATA_CALL_TYPE_IPV4;
			ql_data_call_error_e  err;

			ret = ql_data_call_start( &call_struct , &err );

			if( ret != 0 ){
				std::cerr << "Call fail" << std::endl;
			}
		}catch( err_code e ){
			return -3;
		}
	}else{
		ret = -2;
	}
	return ret;
}

bool ec20dial :: set_apn()
{
	bool ret = false;
	// 打开AT指令操作接口
	std::fstream fs("/dev/smd8" , std::ios_base::in | std::ios_base::out);

	if( fs.is_open() ){
		if( is_apn ){
			fs << "AT+QCTPWDCFG=\"" << user << "\",\""
			   << paswd << "\"\r\n";  // 设置APN 操作，用户和密码
			if( vendor == CTCC ){
				usleep(200000);
				fs << "AT+QCFG=\"cdmaruim\",0";
			}
		}
		else if( vendor == CTCC ) {
			fs << "AT+QCFG=\"cdmaruim\",0";
		}

	}else{
		ret = -1;
	}

	fs.close();

	return ret;
}

int ec20dial :: check_csq()
{
      int ret = 99;
      int e = QL_NW_GetCSQ( &ret );
      if( e ) ret = 99;

      return ret;
}

std::string ec20dial:: GetICCID()
{
	std::string str;
	std::stringstream ss;

	//char data[ 40 ];
	int slot = 0;
	E_QL_SIM_ID_T  simId;

	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar();
	if( ptvar ) ptvar->GetValue( "/simType" , slot );

	switch( slot ){
		case 0:
			simId = E_QL_SIM_EXTERNAL_SLOT_1;
			break;
		case 1:
			simId = E_QL_SIM_EXTERNAL_SLOT_2;
			break;
		case 2:
			simId = E_QL_SIM_EMBEDDED;
			break;
		case 3:
			simId = E_QL_SIM_REMOTE;
			break;
	}
	E_QL_SIM_STATES_T stat = QL_SIM_GetState( simId );
	//int e = -1;
	switch( stat ){
		case E_QL_SIM_STAT_NOT_INSERTED:
			std::cout << "SIM Card is not inserted , get ICCID Fail." << std::endl;
            		StartRebootTimer();
			break;
		case E_QL_SIM_STAT_READY:
		{
			char iccid[ 21 ];
			//e =
			QL_SIM_GetICCID( simId , iccid , 20 );
			iccid[ 20 ] = 0;
			str = iccid;
		}
			break;
		case E_QL_SIM_STAT_PIN_REQ:
		case E_QL_SIM_STAT_PUK_REQ:
		case E_QL_SIM_STAT_BUSY:
			std::cout << "SIM Card is busy , get ICCID Fail." << std::endl;
           		 StartRebootTimer();
			//abort();
            		break;
		case E_QL_SIM_STAT_BLOCKED:
			std::cout << "SIM Card is blocked , get ICCID Fail." << std::endl;
			StartRebootTimer();
            	break;
		case E_QL_SIM_STAT_UNKNOWN:
		default:
			std::cout << "Unknow SIM Card status , get ICCID Fail." << std::endl;
			StartRebootTimer();
	}
	return str;
}

std::string ec20dial :: GetIMEI()
{
	char data[ 16 ];
	std::string ret;
	int e = QL_DEV_GetImei( data , 15 );
	if( e != E_QL_OK ){
		std::cout << "Get IMEI Fail" << std::endl;
	}
	data[ 15 ] = 0;
	ret = data;
	return ret;
}
#if defined( __DIAL_EXEC__ )
// @note 如果需要将程序编译成可执行的拨号程序，那么定义__DIAL_EXEC__ 否则不要定义，将这个模块可以做
//       方便调用的库应用于其他程序
// 将这个程序在模块启动的时候自动运行一次
int main( int argc , const char* argv[] )
{
	int ret = 0;
	std::shared_ptr< CSysVar > ptvar = GetOrCreateSysVar("/data/sndtu/config.xml");

	if( ptvar ){
		ec20dial  dial;

		ret = dial.run();

		while( finish == false ){
			std::this_thread::yield();  // 释放CPU所有权
			usleep( 100000 );
		}
	}
	return ret;
}
#endif
